import { DANA_PACKAGE_ID } from "~~/config";
import type { FetchOptions } from "ofetch";
// import dayjs from "dayjs";
import { showToast } from "vant";
import { useGlobalStore } from "~~/store/global";
import { useEventBus } from "@vueuse/core";
import * as MITO from "@zhj1214/qdjk-web";
import "abortcontroller-polyfill/dist/abortcontroller-polyfill-only";

const showToastEmit = useEventBus("showToast-emit");
interface RequestFetchOptions extends FetchOptions {
  url: string;
}

const offset = new Date().getTimezoneOffset();

class RequestFetch {
  static baseURL: string = "";
  static timeout: number = 15000;
  static headers?: Record<string, string> = {
    Language: "en",
    "Content-Type": "application/json;charset=UTF-8",
    TimeZone: `GMT${offset > 0 ? "-" : "+"}${Math.abs(offset / 60)}`, // morgan 要求传 GMT+x   // timezone 插件可以使用这个获取。 dayjs?.tz?.guess() => Timezone: Asia/Shanghai
  };

  constructor(baseURL?: string, timeout?: number) {
    if (baseURL) {
      RequestFetch.baseURL = baseURL;
    }

    if (timeout) {
      RequestFetch.timeout = timeout;
    }
  }

  async request<T>(data: RequestFetchOptions) {
    // 1.
    const globalStore = useGlobalStore();
    // 2. 取消请求使用案例
    const controller = new AbortController();
    const { signal } = controller;
    const timeoutFn = setTimeout(() => {
      // const { t } = useI18n();
      controller.abort(); // 取消 fetch 请求
      showToastEmit.emit("common.reqTimeOut");
      // showToast("Request Timeout"); // $t("common.reqTimeOut")
    }, RequestFetch.timeout);

    // 3. 配置参数
    const options: FetchOptions = {
      signal,
      baseURL: RequestFetch.baseURL,
      method: data.method ?? "get",
      params: data.params ?? undefined,
      body: data.body ?? undefined,
      headers: {
        ...RequestFetch.headers,
        token: globalStore?.$state.token,
        Language: globalStore?.$state.language,
        packageId: globalStore?.$state.packageId || DANA_PACKAGE_ID.value,
        "Package-Id": globalStore?.$state.packageId || DANA_PACKAGE_ID.value,
      },
      retry: 0, // 请求出错，自动重试
      async onRequestError(context) {
        // 2. Log error
        if (process.server) {
          console.log(
            "onRequestError server fetch request error",
            context.error
          );
        } else if (process.client) {
          console.log("onRequestError client fetch request error", context);
          MITO.log({
            message:
              (context.request || "") +
              " ~RequestError~ " +
              (context.error ? context.error.message : ""),
            tag: "请求发送Request失败",
            level: "low",
            ex: context,
          });
          showToastEmit.emit("common.networkAnomaly");
        }
      },
      onResponseError(context) {
        // 2. Log error
        if (process.server) {
          console.log("server fetch response error", context.error);
        } else if (process.client) {
          console.log("client fetch response error", context);
          MITO.log({
            message:
              (context.response ? context.response.url : "") +
              " ~ResponseError~ " +
              (context.response ? context.response._data : ""),
            tag: "返回失败Response",
            level: "low",
            ex: context,
          });
          showToastEmit.emit("common.networkAnomaly");
        }
      },
      onRequest(context) {
        // 请求之前拦截
        if (process.server) {
          console.log("fetch request", context);
        }
      },
      onResponse(context) {
        // 2. 请求返回拦截
        if (process.server) {
          console.log("server: fetch response", context.response._data);
        } else if (process.client) {
          // 业务code
          switch (context.response._data.code) {
            case 500:
              showToast(context.response._data.message);
              break;
            // 未登录
            case 403: {
              console.error("fetch 用户 token 失效!!");
              jumpLogin();
              break;
            }
            case 1001:
              if (context.response._data?.data?.errors) {
                showToast(context.response._data.data.errors);
              } else {
                showToast(context.response._data?.message);
              }
            default:
              break;
          }
        }
      },
    };

    if (data.headers instanceof Object) {
      options.headers = { ...options.headers, ...data.headers };
    }

    let result = null;
    try {
      result = await $fetch<T>(data.url, options as any);
      clearInterval(timeoutFn);
    } catch (error) {
      clearInterval(timeoutFn);
      console.log("请求失败：", error);
    }

    return result;
  }
}

const requestFetch = new RequestFetch("/api");

const { request } = requestFetch;

export { request, RequestFetch, requestFetch };
